var CoverFlow = new Class({
	options: {
		width: 800,
		height: 200, 
		showing: 7,
		popness: 1.125
	},
	
	initialize: function (options) {
		this.setOptions(options);
		const space = 50;
		
		var workingRect = getMainDisplay().workRect;
		this.$window = $(new Window());
		this.$window.set(
			{
				width: this.options.width + space * 2,
				height: this.options.height,
				vOffset: (workingRect.getMaxY() - this.options.height) / 2,
				hOffset: (workingRect.getMaxX() - this.options.width) / 2
			}
		);
		
		this.$frame = $(new Frame());
		this.$frame.set(
			{
				hOffset: space,
				width: this.options.width,
				height: this.options.height,
				styles: {
					backgroundColor: 'rgba(0,0,0,0)'
				}
			}
		);
		this.$window.adopt(this.$frame);
		
		var scroll = function (event) {
			if (this.$scrolling) {
				return;
			}
		
			this.$scrolling = true;
			if (event.scrollDelta > 0 || event.keyCode == Event.keys.left) {
				this.current--;
				setInfo(this.mouseOver);
			} else if (event.scrollDelta < 0 || event.keyCode == Event.keys.right) {
				this.current++;
				setInfo(this.mouseOver);
			}
		}.bind(this);
		
		this.$window.addEvent('KeyDown', scroll);
		this.$frame.addEvent('MouseWheel', scroll);
		
		this.$albums = Album.getAllEntities("artist_id IS NOT NULL", {title: true});
		this.$all = $A(this.$albums);
		this.$albumImg = [];
		this.$bounds = [];
		
		const gap = 10;
		const imgWidth = (this.options.width - gap * (this.options.showing + 1)) / this.options.showing;
		const imgHeight = imgWidth;
		this.$imgWidth = imgWidth;
		
		for (i = 0; i <= this.options.showing; i++) {
			var img = new AlbumCover(
				new Element('canvas', {
					width: imgWidth, 
					height: imgHeight,
					vOffset: gap,
					hOffset: (imgWidth + gap) * i + gap
				}), {reflection: true});			
			this.$albumImg.push(img);
			this.$bounds.push(img.element.getBounds());
		}
		this.$albumImg.unshift(new AlbumCover(
				new Element('canvas', {
					width: imgWidth, 
					height: imgHeight,
					vOffset: gap,
					hOffset: -imgWidth
				}), {reflection: true}));
		this.$bounds.unshift(this.$albumImg[0].element.getBounds());
		
		this.$pop = (imgWidth * (this.options.popness - 1)).toInt();
		const halfPop = (this.$pop / 2).toInt();
		this.$albumImg.each(function (img){
			img.element.addEvent('MouseEnter', function () {
				if (this.$scrolling) {
					return;
				}
				
				var i = this.$albumImg.indexOf(img);
				this.mouseOver = i;
				setInfo(this.mouseOver);
				img.resize(imgWidth + this.$pop, imgHeight + this.$pop);
				img.element.set({
					hOffset: this.$bounds[i].x - halfPop,
					vOffset: this.$bounds[i].y + halfPop
				});
			}.bind(this))
			.addEvent('MouseExit', function () {
				if (this.$scrolling) {
					return;
				}
				
				var i = this.$albumImg.indexOf(img);
				resetInfo();
				img.resize(imgWidth, imgHeight);
				img.element.set({
					hOffset: this.$bounds[i].x,
					vOffset: this.$bounds[i].y
				});
				delete this.mouseOver;
			}.bind(this))
			.addEvent('Click', function () {
				var index = (this.current + this.$albumImg.indexOf(img) - 1).limit(0, this.$all.length);
				var album = this.$all[index];
				this.fireEvent('onAlbumClicked', album, 0);
			}.bind(this));
		}.bind(this));
		
		this.$infoFrame = new Element('frame',
			{
				vOffset: imgHeight + 20,
				width: this.$frame.width - 20,
				styles: {
					color: 'white',
					fontFamily: "'"+preferences.font.value+"'",
					fontWeight: 'bold',
					textAlign: 'center',
					fontSize: '20px'
				}
			}
		);
		
		var props = {
						width: this.$infoFrame.width
					};
		this.$artistInfo = new Element('text', props);
		this.$titleInfo = new Element('text', props);
		this.$infoFrame.adopt(this.$artistInfo, this.$titleInfo);
		
		var setInfo = function (i) {
			var index = (this.current + i - 1).limit(0, this.$all.length);
			var album = this.$all[index];
			if ($defined(album)) {
				if ($defined(album.artist)) {
					this.$artistInfo.text = album.artist.name;
				}
				this.$titleInfo.text = album.title;
			}
		}.bind(this);
		var resetInfo = function () {
			this.$artistInfo.text = "";
			this.$titleInfo.text = "";
		}.bind(this);
		
		var infos = this.$infoFrame.getChildren();
		infos.each(function (item, index){
			if (item.getTag() == 'text') {
				item.anchorStyle = "topLeft";
			}
			
			if (index == 0) {
				item.vOffset = 0;
			} else {
				item.vOffset = infos[index - 1].getBounds().getMaxY() + 1;
			}
		}.bind(this));
		
		this.$frame.adopt(this.$albumImg.map(function (el) {return el.element;}));
		this.$frame.adopt(this.$infoFrame);
		
		var backdrop = new Element('canvas', {
			vOffset: imgHeight * 0.7 + gap,
			width: this.$window.width,
			height: this.$window.height
		});
		this.$window.adopt(backdrop);
		backdrop.orderBelow(null);
		var ctx = backdrop.getContext("2d");
		ctx.fillStyle = "rgba(0,0,0,0.8)";
		ctx.lineJoin = "round";
		ctx.beginPath();
		ctx.moveTo(space * 1.1, 0);
		ctx.lineTo(backdrop.width - space * 1.1, 0);
		ctx.lineTo(backdrop.width, backdrop.height);
		ctx.lineTo(0, backdrop.height);
		ctx.fill();
		
		var search = new Element('textarea', {
			hOffset: 5,
			columns: 20,
			width: 200,
			lines: 1,
			styles: {
				backgroundColor: 'rgba(60,60,60, 0.6)',
				color: 'white', 
				fontSize: '16px'
			},
			events: {
				KeyUp: function (event) {
					if (event.keyCode == Event.keys.enter) {
						search.loseFocus();
						this.$all = $A(this.$albums);
						this.$all = this.$all.filter(function (album){
							return search.data == '' 
								|| album.artist.name.test(search.data, 'i')
								|| album.title.test(search.data, 'i');
						}.bind(this));
						this.reset();
					}
				}.bind(this)
			}
		});
		search.vOffset = this.$frame.height - search.height - 5;
		this.$frame.adopt(search);
		
		this.current = 0;
	},
	
	$setImage: function (img, index, animate) {
		animate = $pick(animate, true);
		if (index >= 0 && index < this.$all.length) {
			if (animate) {
				animator.start(new FadeAnimation(img.element,
					255, 500, animator.kEaseInOut));
			} else {
				img.opacity = 255;
			}
			img.src = this.$all[index].cover_path;
		} else {
			if (animate) {
				animator.start(new FadeAnimation(img.element, 
					0, 500, animator.kEaseInOut));
			} else {
				img.opacity = 0;
			}
		}
	},
	
	reset: function () {
		this.$albumImg.each(function (img) {
			this.$setImage(img, -1, false);
		}.bind(this));
		this.$current = 0;
		this.$albumImg.each(function (img, i) {
			this.$setImage(img, this.$current + i - 1, true);
		}.bind(this));
	},
	
	get current () {
		return this.$current;
	},
	
	set current (val) {
		const duration = 500;
		var oldVal = this.$current;
		const max = this.$all.length - this.options.showing;
		this.$current = val.limit(0, max < 0 ? 0 : max);
		if (oldVal === undefined) {
			this.reset();
		} else if (oldVal != this.$current) {
			var dir = (oldVal - this.$current).limit(-1, 1);
			var movedAlready;
			
			var insert = function (remove, add, index, bounds) {
				var i = remove();
				this.$setImage(i, index, false);
				i.element.hOffset = bounds.getMinX();
				add(i);
				movedAlready = this.$albumImg.indexOf(i);
			}.bind(this);
			
			if (dir < 0) {
				insert(this.$albumImg.shift.bind(this.$albumImg), 
				  this.$albumImg.push.bind(this.$albumImg),
				  this.$current + this.$albumImg.length - 2,
				  this.$bounds.getLast());
			} else if (dir > 0) {
				insert(this.$albumImg.pop.bind(this.$albumImg), 
				  this.$albumImg.unshift.bind(this.$albumImg),
				  this.$current - 1,
				  this.$bounds[0]);
			}
			
			var scrollDone = function () {
				this.$scrolling = false;
			}.bind(this);
			
			const halfPop = (this.$pop / 2).toInt();
			
			var fadeIn = dir < 0 ? this.$albumImg.length - 2 : 1;
			var fadeOut = dir < 0 ? 0 : this.$albumImg.length - 1;
			
			this.$albumImg[fadeIn].opacity = 0;
			animator.start(new FadeAnimation(
				this.$albumImg[fadeIn].element, 
				255, 
				duration, animator.kEaseInOut));
			animator.start(new FadeAnimation(
				this.$albumImg[fadeOut].element, 
				0, 
				duration, animator.kEaseInOut, function () {
					this.$albumImg[fadeOut].opacity = 255;
				}.bind(this)));
			
			this.$albumImg.each(function (img, i) {
				if (i === movedAlready) {
					return;
				}
				
				var x = this.$bounds[i].x - ((i == (this.mouseOver + dir)) ? halfPop : 0);
				var y = this.$bounds[0].y + ((i == (this.mouseOver + dir)) ? halfPop : 0);
				
				animator.start(new MoveAnimation(img.element, 
					x, y, duration, animator.kEaseInOut,
					i == 1 ? scrollDone : undefined));
			}.bind(this));
		} else {
			this.$scrolling = false;
		}
	}

});
CoverFlow.implement(new Options, new Events);